/* MQTT (over TCP) Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/

#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include "esp_wifi.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "protocol_examples_common.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"

#include "lwip/sockets.h"
#include "lwip/dns.h"
#include "lwip/netdb.h"

#include "esp_log.h"
#include "my_dev_init.h"
#include "mqtt_client.h"
#include "my_json_parse.h"
#include "my_dev_config.h"
#include "my_dev_info.h"
#include "my_led.h"
#include "my_dev_net_config.h"
#include "my_dev_info.h"


static const char *TAG = "MQTT_EXAMPLE";
esp_mqtt_client_handle_t g_client = NULL;
mqtt_client_parameter mqtt_client_p;


/*************************************************************
 * 通过MQTT发送串口数据
 * **************************************************************/
void my_mqtt_send(char * data)
{
    ESP_LOGI(TAG,"%s\n",data);
    ESP_LOGI(TAG, "pub_topic: %s\r\n", mqtt_client_p.public_topic);
    int msg_id = esp_mqtt_client_publish(g_client, mqtt_client_p.public_topic, data, 0, 1, 0);
    ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
    return;
}



static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event)
{
    esp_mqtt_client_handle_t client = event->client;
    g_client = event->client;
    int msg_id;
    // your_context_t *context = event->context;
    switch (event->event_id) {
        case MQTT_EVENT_CONNECTED:
            led_operation(INTERNET_INDICATOR_LED, LED_ON);  //网络指示灯
            //订阅主题
            msg_id = esp_mqtt_client_subscribe(client, mqtt_client_p.subscribe_topic, 0);
            // msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0);
            ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
                // char data[] = "123456";
                // my_mqtt_send(data);
            break;

        case MQTT_EVENT_DISCONNECTED:       //MQTT断开
            ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
            led_operation(INTERNET_INDICATOR_LED, LED_OFF);  //网络指示灯
            break;

        case MQTT_EVENT_SUBSCRIBED:
            ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
            break;

        case MQTT_EVENT_UNSUBSCRIBED:
            ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
            break;

        case MQTT_EVENT_PUBLISHED:
            ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
            break;

        case MQTT_EVENT_DATA:       //recv mqtt server data 
            ESP_LOGI(TAG,"TOPIC=%.*s\t", event->topic_len, event->topic);
            ESP_LOGI(TAG,"recv data=%.*s\r\n", event->data_len, event->data);
            //解析mqtt server数据
            mqtt_tranport_data mqtt_tranport_data_t =  parse_mqtt_user_data(event->data);
            // printf("opcode:%s\t addr:%s\tdata:%s\n",mqtt_tranport_data_t.opcode,mqtt_tranport_data_t.addr,mqtt_tranport_data_t.data);
            xQueueSend(mqtt_queue,(void *)&mqtt_tranport_data_t, (TickType_t)10);
            break;

        case MQTT_EVENT_ERROR:
            ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
            break;

        default:
            ESP_LOGI(TAG, "Other event id:%d", event->event_id);
            break;
    }
    return ESP_OK;
}

static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) {
    ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%d", base, event_id);
    mqtt_event_handler_cb(event_data);
}


/**************************************************************************
 * MQTT 心跳任务函数
 * ************************************************************************/
void heart_ping_page(void *p)
{
    int msg_id;
    uint8_t mac[6];
    char redwood_ping[50] = {0};
    // esp_read_mac(mac_addr, ESP_MAC_WIFI_STA)  
    if(esp_read_mac(mac, ESP_MAC_WIFI_STA) != OK)
    {
        ESP_LOGE(TAG, "get MAC address Fail !!!");
        return;
    }
    sprintf(redwood_ping,"{\"data\":\"FFFFFFFF\",\"mac\":\"%02X%02X%02X%02X%02X%02X\"}",
                mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
    wait_for_ip();
    while (1)
    {
        msg_id = esp_mqtt_client_publish(g_client, "To_Heart_Page", redwood_ping, 0, 1, 0);
        if(msg_id == -1){
            ESP_LOGE(TAG, "mqtt heart failed msg_id=%d",msg_id);
            led_operation(INTERNET_INDICATOR_LED, LED_OFF);  //网络指示灯
        }else{
            ESP_LOGI(TAG, "sent mqtt heart successful, msg_id=%d", msg_id);
            led_operation(INTERNET_INDICATOR_LED, LED_ON);  //网络指示灯
        }
        vTaskDelay(MQTT_HEARBEAT_TIME * 1000 / portTICK_PERIOD_MS);
    }

    vTaskDelete(NULL);
}

void esp_mqtt_app_start(void)
{

    // ESP_ERROR_CHECK(nvs_flash_init());
    // ESP_ERROR_CHECK(esp_netif_init());
    // ESP_ERROR_CHECK(esp_event_loop_create_default());

    // /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
    //  * Read "Establishing Wi-Fi or Ethernet Connection" section in
    //  * examples/protocols/README.md for more information about this function.
    //  */
    // ESP_ERROR_CHECK(example_connect());



    /* 获取模组MAC地址，并作为MQTT客户端ID */
    uint8_t mac[6];
    char id_string[13] = {0};
    esp_read_mac(mac, ESP_MAC_WIFI_STA);
    sprintf(id_string, "%02X%02X%02X%02X%02X%02X", mac[0], mac[1], mac[2],mac[3], mac[4], mac[5]);
    id_string[12] = '\0';

    read_mqtt_client_data(&mqtt_client_p);
    my_printf(mqtt_client_p);

    esp_mqtt_client_config_t mqtt_cfg = {
        .host = mqtt_client_p.host,
        // .uri = mqtt_client_p.host,
        .port = mqtt_client_p.port,
        .disable_auto_reconnect = false,
        .keepalive = mqtt_client_p.heartbeat,
        .client_id = id_string,
        .lwt_qos = mqtt_client_p.qos,
        .username = mqtt_client_p.username,
        .password = mqtt_client_p.passwd,
    };

    esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
    esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, client);
    esp_mqtt_client_start(client);

    xTaskCreate(heart_ping_page, "ping_task", 2048, NULL, 8, NULL);
}

